// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** File:    IChannel.cs 
**
** 
** Purpose: Defines the interfaces implemented by channels
**
**
===========================================================*/ 
namespace System.Runtime.Remoting.Channels {
    using System.Collections; 
    using System.IO; 
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Messaging; 
    using System.Runtime.Remoting.Metadata;
    using System.Security.Permissions;
    using System;
    using System.Globalization; 

[System.Runtime.InteropServices.ComVisible(true)] 
    public interface IChannel 
    {
        int ChannelPriority 
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
        } 
        String ChannelName
        { 
            [System.Security.SecurityCritical]  // auto-generated_required 
            get;
        } 
        [System.Security.SecurityCritical]  // auto-generated_required
        String Parse(String url, out String objectURI);
    }
 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IChannelSender : IChannel 
    { 
        [System.Security.SecurityCritical]  // auto-generated_required
        IMessageSink CreateMessageSink(String url, Object remoteChannelData, out String objectURI); 
    } // interface IChannelSender

[System.Runtime.InteropServices.ComVisible(true)]
    public interface IChannelReceiver : IChannel 
    {
        Object ChannelData 
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get; 
        }
        [System.Security.SecurityCritical]  // auto-generated_required
        String[] GetUrlsForUri(String objectURI);
        [System.Security.SecurityCritical]  // auto-generated_required 
        void StartListening(Object data);
        [System.Security.SecurityCritical]  // auto-generated_required 
        void StopListening(Object data); 
    } // interface IChannelReceiver
 

[System.Runtime.InteropServices.ComVisible(true)]
    public interface IChannelReceiverHook
    { 
        String ChannelScheme
        { 
            [System.Security.SecurityCritical]  // auto-generated_required 
            get;
        } 

        bool WantsToListen
        {
            [System.Security.SecurityCritical]  // auto-generated_required 
            get;
        } 
 
        IServerChannelSink ChannelSinkChain
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
        }
 
        [System.Security.SecurityCritical]  // auto-generated_required
        void AddHookChannelUri(String channelUri); 
 
    } // interface IChannelReceiverHook
 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IClientChannelSinkProvider
    {
        [System.Security.SecurityCritical]  // auto-generated_required 
        IClientChannelSink CreateSink(IChannelSender channel, String url, Object remoteChannelData);
 
        IClientChannelSinkProvider Next 
        {
            [System.Security.SecurityCritical]  // auto-generated_required 
            get;
            [System.Security.SecurityCritical]  // auto-generated_required
            set;
        } 
    } // interface IClientChannelSinkProvider
 
 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IServerChannelSinkProvider 
    {
        // The sink provider should also chain this call to the next provider in the chain.
        [System.Security.SecurityCritical]  // auto-generated_required
        void GetChannelData(IChannelDataStore channelData); 

        [System.Security.SecurityCritical]  // auto-generated_required 
        IServerChannelSink CreateSink(IChannelReceiver channel); 

        IServerChannelSinkProvider Next 
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
            [System.Security.SecurityCritical]  // auto-generated_required 
            set;
        } 
    } // interface IServerChannelSinkProvider 

 
    // This has the same exact functionality as IClientChannelSinkProvider.
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IClientFormatterSinkProvider : IClientChannelSinkProvider
    { 
    } // interface IClientFormatterSinkProvider
 
 
    // This has the same exact functionality as IServerChannelSinkProvider.
    // There may be multiple formatter sinks. If there are more than one, then one 
    // formatter sink may decide to delegate the formatting responsibilities to the next
    // one.
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IServerFormatterSinkProvider : IServerChannelSinkProvider 
    {
    } // interface IServerFormatterSinkProvider 
 

 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IClientChannelSink : IChannelSinkBase
    {
        // Parameters: 
        //   msg - it's the "IMethodCallMessage"
        //   requestHeaders - headers to add to the outgoing message heading to server 
        //   requestStream - stream headed towards the transport sink 
        //   responseHeaders - headers that server returned
        //   responseStream - stream coming back from the transport sink 
        [System.Security.SecurityCritical]  // auto-generated_required
        void ProcessMessage(IMessage msg,
                            ITransportHeaders requestHeaders, Stream requestStream,
                            out ITransportHeaders responseHeaders, out Stream responseStream); 

        // Parameters: (for async calls, the transport sink is responsible for doing the write 
        //     and read asynchronously) 
        //   sinkStack - channel sinks who called this one
        //   msg - it's the "IMessage" msg 
        //   headers - headers to add to the outgoing message heading to server
        //   stream - stream headed towards the transport sink
        // Returns:
        //   IAsyncResult for this call. 
        [System.Security.SecurityCritical]  // auto-generated_required
        void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, 
                                 ITransportHeaders headers, Stream stream); 

        [System.Security.SecurityCritical]  // auto-generated_required 
        void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, Object state,
                                  ITransportHeaders headers, Stream stream);

        // Parameters: 
        //   msg - it's the "IMethodCallMessage"
        //   headers - headers to add to the outgoing message heading to server 
        [System.Security.SecurityCritical]  // auto-generated_required 
        Stream GetRequestStream(IMessage msg, ITransportHeaders headers);
 

        // the next channel sink in the chain
        IClientChannelSink NextChannelSink
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get; 
        } 
    } // IClientChannelSink
 


    [Serializable]
[System.Runtime.InteropServices.ComVisible(true)] 
    public enum ServerProcessing
    { 
        Complete, // server synchronously processed message 
        OneWay,   // message dispatched and no response should be sent
        Async     // the call was dispatched asynchronously 
                  //   (sink should store data on stack for later processing)
    } // ServerProcessing

 
    // Used for security sink and transport sinks.
[System.Runtime.InteropServices.ComVisible(true)] 
    public interface IServerChannelSink : IChannelSinkBase 
    {
        // Parameters: 
        //   sinkStack - channel sinks who called this one
        //   requestMsg - deserialized request message or null if the stream hasn't been deserialized
        //   requestHeaders - headers retrieved from the incoming message from client
        //   requestStream - stream to process and pass onto towards the deserialization sink. 
        //   responseMsg - response message
        //   responseHeaders - headers to add to return message heading to client 
        //   responseStream - stream heading back towards the transport sink 
        // Returns:
        //   Provides information about how message was processed. 
        [System.Security.SecurityCritical]  // auto-generated_required
        ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
                                        IMessage requestMsg,
                                        ITransportHeaders requestHeaders, Stream requestStream, 
                                        out IMessage responseMsg, out ITransportHeaders responseHeaders,
                                        out Stream responseStream); 
 
        // Parameters: (for async calls)
        //   sinkStack - sink stack (leading back to the server transport sink) 
        //   headers - headers to add to return message heading to client
        //   stream - stream heading back towards the transport sink
        [System.Security.SecurityCritical]  // auto-generated_required
        void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, Object state, 
                                  IMessage msg, ITransportHeaders headers, Stream stream);
 
        // Parameters: 
        //   sinkStack - sink stack (leading back to the server transport sink)
        //   state - state that had been pushed to the stack by this sink 
        //   msg - it's the "IMethodCallMessage"
        //   headers - headers to put in response message to client
        [System.Security.SecurityCritical]  // auto-generated_required
        Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, Object state, 
                                 IMessage msg, ITransportHeaders headers);
 
 
        // the next channel sink in the chain
        IServerChannelSink NextChannelSink 
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
        } 

    } // interface IServerChannelSink 
 

[System.Runtime.InteropServices.ComVisible(true)] 
    public interface IChannelSinkBase
    {
        // This returns a dictionary through which properties on the sink may be retrieved
        // or configured. If a property is not present in this sink, it should delegate the 
        // the property get or set to the next sink in the chain.
        IDictionary Properties 
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get; 
        }
    }

 

    // Client formatter sinks are both a message sink and a channel sink. 
    // They initially transform the message into a stream. 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IClientFormatterSink : IMessageSink, IClientChannelSink 
    {
    } // interface IClientFormatterSink

 

 
    // Channels wishing to use the channel sink architecture must implement this interface 
    //   on their ChannelData object.
[System.Runtime.InteropServices.ComVisible(true)] 
    public interface IChannelDataStore
    {
        String[] ChannelUris
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get; 
        } 

        Object this[Object key] 
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
            [System.Security.SecurityCritical]  // auto-generated_required 
            set;
        } 
    } // interface IChannelDataStore 

 
    // Used to store channel data for our remoting channels
    [System.Security.SecurityCritical]  // auto-generated_required
    [Serializable]
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
    [System.Runtime.InteropServices.ComVisible(true)]
    public class ChannelDataStore : IChannelDataStore 
    { 
        String[]           _channelURIs;  // list of channel uri's that map to this channel
 
        DictionaryEntry[]  _extraData;    // sink data

        // private constructor for shallow clone
        private ChannelDataStore(String[] channelUrls, DictionaryEntry[] extraData) 
        {
            _channelURIs = channelUrls; 
            _extraData = extraData; 
        }
 
        public ChannelDataStore(String[] channelURIs)
        {
            _channelURIs = channelURIs;
            _extraData = null; 
        }
 
        [System.Security.SecurityCritical]  // auto-generated 
        internal ChannelDataStore InternalShallowCopy()
        { 
            return new ChannelDataStore(_channelURIs, _extraData);
        }

 
        public String[] ChannelUris
        { 
            [System.Security.SecurityCritical] 
            get { return _channelURIs; }
            set { _channelURIs = value; } 
        }

        // implementation of IChannelDataStore
        public Object this[Object key] 
        {
            [System.Security.SecurityCritical] 
            get 
            {
                // look for matching key in extra data list 
                foreach (DictionaryEntry entry in _extraData)
                {
                    if (entry.Key.Equals(key))
                        return entry.Value; 
                }
 
                // entry not found 
                return null;
            } // get 

            [System.Security.SecurityCritical]
            set
            { 
                if (_extraData == null)
                { 
                    _extraData = new DictionaryEntry[1]; 
                    _extraData[0] = new DictionaryEntry(key, value);
                } 
                else
                {
                    int length =_extraData.Length;
                    DictionaryEntry[] newList = new DictionaryEntry[length + 1]; 
                    int co = 0;
                    for (; co < length; co++) 
                        newList[co] = _extraData[co]; 
                    newList[co] = new DictionaryEntry(key, value); // set last value
                    _extraData = newList; 
                }
            } // set
        } // Object this[Object key]
 
    } // class ChannelDataStore
 
 

 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface ITransportHeaders
    {
        // Should add headers in order, and remove them if somebody tries to set 
        //   it to null.
        Object this[Object key] 
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get; 
            [System.Security.SecurityCritical]  // auto-generated_required
            set;
        }
 
        // This is required to handback an enumerator which iterates over all entries
        //   in the headers. 
        [System.Security.SecurityCritical]  // auto-generated_required 
        IEnumerator GetEnumerator();
    } // interface ITransportHeaders 


    // TransportHeaders is used to store a collection of headers that is used in the channel sinks.
    // The header list preserves order, and keeps headers in the order that they were originally 
    // added. You can use the foreach statement to iterate over the contents of the header list
    // which contains objects of type DictionaryEntry. Keys are required to be strings, and 
    // comparisons are done on a case-insensitive basis. 
    [System.Security.SecurityCritical]  // auto-generated_required
    [Serializable] 
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)]
    [System.Runtime.InteropServices.ComVisible(true)]
    public class TransportHeaders : ITransportHeaders
    { 
        private ArrayList _headerList; // array of type DictionaryEntry
 
        public TransportHeaders() 
        {
            // The default capacity is larger than we'll typically need so start off at 6. 
            _headerList = new ArrayList(6);
        } // TransportHeaders

 
        // dictionary like interface
        public Object this[Object key] 
        { 
            [System.Security.SecurityCritical]
            get 
            {
                String strKey = (String)key;

                // look for matching key in header list 
                foreach (DictionaryEntry entry in _headerList)
                { 
                    if (String.Compare((String)entry.Key, strKey, StringComparison.OrdinalIgnoreCase) == 0) 
                        return entry.Value;
                } 

                // entry not found
                return null;
            } // get 

            [System.Security.SecurityCritical] 
            set 
            {
                if (key == null) 
                    return;

                String strKey = (String)key;
 
                // remove this entry if it's already in the list
                int co = _headerList.Count - 1; 
                while (co >= 0) 
                {
                    String headerKey = (String)((DictionaryEntry)_headerList[co]).Key; 
                    if (String.Compare(headerKey, strKey, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        _headerList.RemoveAt(co);
                        break; 
                    }
                    co--; 
                } 

                // otherwise, add this entry 
                if (value != null)
                {
                    _headerList.Add(new DictionaryEntry(key, value));
                } 
            } // set
        } // Object this[Object key] 
 
        [System.Security.SecurityCritical]
        public IEnumerator GetEnumerator() 
        {
            return _headerList.GetEnumerator();
        } // GetEnumerator
 
    } // TransportHeaders
 
 

    // All sink providers must have a constructor that accepts a hashtable and 
    //   an ArrayList of these structures if they want to be used from a config file.
[System.Runtime.InteropServices.ComVisible(true)]
    public class SinkProviderData
    { 
        private String _name;
        private Hashtable _properties = new Hashtable(StringComparer.InvariantCultureIgnoreCase); 
        private ArrayList _children = new ArrayList(); 

        public SinkProviderData(String name) 
        {
            _name = name;
        }
 
        public String Name { get { return _name; } }
        public IDictionary Properties { get { return _properties; } } 
        public IList Children { get { return _children; } } 
    } // class SinkProviderData
 



 
    // Base implementation for channel sinks that want to supply properties.
    // The derived class only needs to implement the Keys property and this[]. 
    [System.Security.SecurityCritical]  // auto-generated_required 
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)]
    [System.Runtime.InteropServices.ComVisible(true)] 
    public abstract class BaseChannelSinkWithProperties : BaseChannelObjectWithProperties
    {
        protected BaseChannelSinkWithProperties() : base()
        { 
        }
    } // class BaseChannelSinkWithProperties 
 

    // This provides a base implementation of a channel that wants 
    // to provide a dictionary interface. It handles the complexity
    // of asking a channel sink chain for their properties.
    // Once the channel constructs its sink chain (usually only applicable
    // for server channels) it should set the SinksWithProperties property. 
    // The properties only get chained for channel sinks when the users asks
    // for the "Properties" dictionary. If you just go through the dictionary interface 
    // you'll only get the channel specific properties. 
    // The derived class only needs to implement the Keys property and this[].
    [System.Security.SecurityCritical]  // auto-generated_required 
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)]
    [System.Runtime.InteropServices.ComVisible(true)]
    public abstract class BaseChannelWithProperties : BaseChannelObjectWithProperties
    { 
        protected IChannelSinkBase SinksWithProperties = null;
 
        protected BaseChannelWithProperties() : base() 
        {
        } 

        // This is overridden so that server channels can expose the properties
        //   of their channel sinks through a flat dictionary interface.
        public override IDictionary Properties 
        {
            [System.Security.SecurityCritical]  // auto-generated_required 
            get 
            {
                // collect dictionaries for all channel sinks and return 
                //   aggregate dictionary
                ArrayList dictionaries = new ArrayList();

                // add the channel itself 
                dictionaries.Add(this);
 
                if (SinksWithProperties != null) 
                {
                    IServerChannelSink srvSink = SinksWithProperties as IServerChannelSink; 
                    if (srvSink != null)
                    {
                        while (srvSink != null)
                        { 
                            IDictionary dict = srvSink.Properties;
                            if (dict != null) 
                                dictionaries.Add(dict); 

                            srvSink = srvSink.NextChannelSink; 
                        }
                    }
                    else
                    { 
                        // we know it's a client channel sink
                        IClientChannelSink chnlSink = (IClientChannelSink)SinksWithProperties; 
 
                        while (chnlSink != null)
                        { 
                            IDictionary dict = chnlSink.Properties;
                            if (dict != null)
                                dictionaries.Add(dict);
 
                            chnlSink = chnlSink.NextChannelSink;
                        } 
                    } 
                }
 
                // return a dictionary that spans all dictionaries provided
                return new AggregateDictionary(dictionaries);
            }
        } 

    } // class BaseChannelWithProperties 
 

 



 
    // Base implementation for channel sinks that want to supply properties.
    // The derived class only needs to implement the Keys property and this[]. 
    [System.Security.SecurityCritical]  // auto-generated_required 
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)]
    [System.Runtime.InteropServices.ComVisible(true)] 
    public abstract class BaseChannelObjectWithProperties : IDictionary
    {
        protected BaseChannelObjectWithProperties()
        { 
        }
 
        public virtual IDictionary Properties { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get { return this; } 
        }

        //
        // IDictionary implementation 
        //
 
        public virtual Object this[Object key] 
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get { return null; }
            [System.Security.SecuritySafeCritical] // overrides public transparent member
            set { throw new NotImplementedException(); }
        } // Object this[Object key] 

        public virtual ICollection Keys 
        { 
            [System.Security.SecuritySafeCritical] // overrides public transparent member
            get { return null; } 
        }

        public virtual ICollection Values
        { 
            [System.Security.SecuritySafeCritical] // overrides public transparent member
            get 
            { 
                ICollection keys = Keys;
                if (keys == null) 
                    return null;

                ArrayList values = new ArrayList();
                foreach (Object key in keys) 
                {
                    values.Add(this[key]); 
                } 

                return values; 
            }
        }

        [System.Security.SecuritySafeCritical] // overrides public transparent member 
        public virtual bool Contains(Object key)
        { 
            if (key == null) 
                return false;
 
            ICollection keySet = Keys;
            if (keySet == null)
                return false;
 
            String keyStr = key as String;
 
            foreach (Object someKey in keySet) 
            {
                if (keyStr != null) 
                {
                    String someKeyStr = someKey as String;
                    if (someKeyStr != null)
                    { 
                        // compare the key strings case-insensitively
                        if (String.Compare(keyStr, someKeyStr, StringComparison.OrdinalIgnoreCase) == 0) 
                            return true; 

                        continue; 
                    }
                }

                if (key.Equals(someKey)) 
                    return true;
            } 
 
            return false;
        } // Contains 

        public virtual bool IsReadOnly
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get { return false; }
        } 
        public virtual bool IsFixedSize 
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get { return true; }
        }

        // The following three methods should never be implemented because 
        // they don't apply to the way IDictionary is being used in this case
        // (plus, IsFixedSize returns true.) 
        [System.Security.SecuritySafeCritical] // overrides public transparent member 
        public virtual void Add(Object key, Object value) { throw new NotSupportedException(); }
        [System.Security.SecuritySafeCritical] // overrides public transparent member 
        public virtual void Clear() { throw new NotSupportedException(); }
        [System.Security.SecuritySafeCritical] // overrides public transparent member
        public virtual void Remove(Object key) { throw new NotSupportedException(); }
 
        [System.Security.SecuritySafeCritical] // overrides public transparent member
        public virtual IDictionaryEnumerator GetEnumerator() 
        { 
            return new DictionaryEnumeratorByKeys(this);
        } // GetEnumerator 


        //
        // end of IDictionary implementation 
        //
 
        // 
        // ICollection implementation
        // 

         //ICollection

        [System.Security.SecuritySafeCritical] // overrides public transparent member 
        public virtual void CopyTo(Array array, int index) { throw new NotSupportedException(); }
 
        public virtual int Count 
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get
            {
                ICollection keySet = Keys;
                if (keySet == null) 
                    return 0;
 
                return keySet.Count; 
            }
        } // Count 

        public virtual Object SyncRoot
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get { return this; }
        } 
        public virtual bool IsSynchronized 
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get { return false; }
        }

        // 
        // end of ICollection implementation
        // 
 
        //IEnumerable
        /// <internalonly/> 
        [System.Security.SecuritySafeCritical] // overrides public transparent member
        IEnumerator IEnumerable.GetEnumerator()
        {
            return new DictionaryEnumeratorByKeys(this); 
        }
 
    } // class BaseChannelObjectWithProperties 

 

    // an enumerator based off of a key set
    internal class DictionaryEnumeratorByKeys : IDictionaryEnumerator
    { 
        IDictionary _properties;
        IEnumerator _keyEnum; 
 
        public DictionaryEnumeratorByKeys(IDictionary properties)
        { 
            _properties = properties;
            _keyEnum = properties.Keys.GetEnumerator();
        } // PropertyEnumeratorByKeys
 
        public bool MoveNext() { return _keyEnum.MoveNext(); }
        public void Reset() { _keyEnum.Reset(); } 
        public Object Current { get { return Entry; } } 

        public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } } 

        public Object Key { get { return _keyEnum.Current; } }
        public Object Value { get { return _properties[Key]; } }
 
    } // DictionaryEnumeratorByKeys
 
 
    // combines multiple dictionaries into one
    //   (used for channel sink properties 
    internal class AggregateDictionary : IDictionary
    {
        private ICollection _dictionaries;
 
        public AggregateDictionary(ICollection dictionaries)
        { 
            _dictionaries = dictionaries; 
        } // AggregateDictionary
 
        //
        // IDictionary implementation
        //
 
        public virtual Object this[Object key]
        { 
            get 
            {
                foreach (IDictionary dict in _dictionaries) 
                {
                    if (dict.Contains(key))
                        return dict[key];
                } 

                return null; 
            } 

            set 
            {
                foreach (IDictionary dict in _dictionaries)
                {
                    if (dict.Contains(key)) 
                        dict[key] = value;
                } 
            } 
        } // Object this[Object key]
 
        public virtual ICollection Keys
        {
            get
            { 
                ArrayList keys = new ArrayList();
                // add keys from every dictionary 
                foreach (IDictionary dict in _dictionaries) 
                {
                    ICollection dictKeys = dict.Keys; 
                    if (dictKeys != null)
                    {
                        foreach (Object key in dictKeys)
                        { 
                            keys.Add(key);
                        } 
                    } 
                }
 
                return keys;
            }
        } // Keys
 
        public virtual ICollection Values
        { 
            get 
            {
                ArrayList values = new ArrayList(); 
                // add values from every dictionary
                foreach (IDictionary dict in _dictionaries)
                {
                    ICollection dictValues = dict.Values; 
                    if (dictValues != null)
                    { 
                        foreach (Object value in dictValues) 
                        {
                            values.Add(value); 
                        }
                    }
                }
 
                return values;
            } 
        } // Values 

        public virtual bool Contains(Object key) 
        {
            foreach (IDictionary dict in _dictionaries)
            {
                if (dict.Contains(key)) 
                    return true;
            } 
 
            return false;
        } // Contains 

        public virtual bool IsReadOnly { get { return false; } }
        public virtual bool IsFixedSize { get { return true; } }
 
        // The following three methods should never be implemented because
        // they don't apply to the way IDictionary is being used in this case 
        // (plus, IsFixedSize returns true.) 
        public virtual void Add(Object key, Object value) { throw new NotSupportedException(); }
        public virtual void Clear() { throw new NotSupportedException(); } 
        public virtual void Remove(Object key) { throw new NotSupportedException(); }

        public virtual IDictionaryEnumerator GetEnumerator()
        { 
            return new DictionaryEnumeratorByKeys(this);
        } // GetEnumerator 
 

        // 
        // end of IDictionary implementation
        //

        // 
        // ICollection implementation
        // 
 
        //ICollection
 
        public virtual void CopyTo(Array array, int index) { throw new NotSupportedException(); }

        public virtual int Count
        { 
            get
            { 
                int count = 0; 

                foreach (IDictionary dict in _dictionaries) 
                {
                    count += dict.Count;
                }
 
                return count;
            } 
        } // Count 

        public virtual Object SyncRoot { get { return this; } } 
        public virtual bool IsSynchronized { get { return false; } }

        //
        // end of ICollection implementation 
        //
 
        //IEnumerable 
        IEnumerator IEnumerable.GetEnumerator()
        { 
            return new DictionaryEnumeratorByKeys(this);
        }

    } // class AggregateDictionary 

 
 
} // namespace System.Runtime.Remoting

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** File:    IChannel.cs 
**
** 
** Purpose: Defines the interfaces implemented by channels
**
**
===========================================================*/ 
namespace System.Runtime.Remoting.Channels {
    using System.Collections; 
    using System.IO; 
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Messaging; 
    using System.Runtime.Remoting.Metadata;
    using System.Security.Permissions;
    using System;
    using System.Globalization; 

[System.Runtime.InteropServices.ComVisible(true)] 
    public interface IChannel 
    {
        int ChannelPriority 
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
        } 
        String ChannelName
        { 
            [System.Security.SecurityCritical]  // auto-generated_required 
            get;
        } 
        [System.Security.SecurityCritical]  // auto-generated_required
        String Parse(String url, out String objectURI);
    }
 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IChannelSender : IChannel 
    { 
        [System.Security.SecurityCritical]  // auto-generated_required
        IMessageSink CreateMessageSink(String url, Object remoteChannelData, out String objectURI); 
    } // interface IChannelSender

[System.Runtime.InteropServices.ComVisible(true)]
    public interface IChannelReceiver : IChannel 
    {
        Object ChannelData 
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get; 
        }
        [System.Security.SecurityCritical]  // auto-generated_required
        String[] GetUrlsForUri(String objectURI);
        [System.Security.SecurityCritical]  // auto-generated_required 
        void StartListening(Object data);
        [System.Security.SecurityCritical]  // auto-generated_required 
        void StopListening(Object data); 
    } // interface IChannelReceiver
 

[System.Runtime.InteropServices.ComVisible(true)]
    public interface IChannelReceiverHook
    { 
        String ChannelScheme
        { 
            [System.Security.SecurityCritical]  // auto-generated_required 
            get;
        } 

        bool WantsToListen
        {
            [System.Security.SecurityCritical]  // auto-generated_required 
            get;
        } 
 
        IServerChannelSink ChannelSinkChain
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
        }
 
        [System.Security.SecurityCritical]  // auto-generated_required
        void AddHookChannelUri(String channelUri); 
 
    } // interface IChannelReceiverHook
 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IClientChannelSinkProvider
    {
        [System.Security.SecurityCritical]  // auto-generated_required 
        IClientChannelSink CreateSink(IChannelSender channel, String url, Object remoteChannelData);
 
        IClientChannelSinkProvider Next 
        {
            [System.Security.SecurityCritical]  // auto-generated_required 
            get;
            [System.Security.SecurityCritical]  // auto-generated_required
            set;
        } 
    } // interface IClientChannelSinkProvider
 
 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IServerChannelSinkProvider 
    {
        // The sink provider should also chain this call to the next provider in the chain.
        [System.Security.SecurityCritical]  // auto-generated_required
        void GetChannelData(IChannelDataStore channelData); 

        [System.Security.SecurityCritical]  // auto-generated_required 
        IServerChannelSink CreateSink(IChannelReceiver channel); 

        IServerChannelSinkProvider Next 
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
            [System.Security.SecurityCritical]  // auto-generated_required 
            set;
        } 
    } // interface IServerChannelSinkProvider 

 
    // This has the same exact functionality as IClientChannelSinkProvider.
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IClientFormatterSinkProvider : IClientChannelSinkProvider
    { 
    } // interface IClientFormatterSinkProvider
 
 
    // This has the same exact functionality as IServerChannelSinkProvider.
    // There may be multiple formatter sinks. If there are more than one, then one 
    // formatter sink may decide to delegate the formatting responsibilities to the next
    // one.
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IServerFormatterSinkProvider : IServerChannelSinkProvider 
    {
    } // interface IServerFormatterSinkProvider 
 

 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IClientChannelSink : IChannelSinkBase
    {
        // Parameters: 
        //   msg - it's the "IMethodCallMessage"
        //   requestHeaders - headers to add to the outgoing message heading to server 
        //   requestStream - stream headed towards the transport sink 
        //   responseHeaders - headers that server returned
        //   responseStream - stream coming back from the transport sink 
        [System.Security.SecurityCritical]  // auto-generated_required
        void ProcessMessage(IMessage msg,
                            ITransportHeaders requestHeaders, Stream requestStream,
                            out ITransportHeaders responseHeaders, out Stream responseStream); 

        // Parameters: (for async calls, the transport sink is responsible for doing the write 
        //     and read asynchronously) 
        //   sinkStack - channel sinks who called this one
        //   msg - it's the "IMessage" msg 
        //   headers - headers to add to the outgoing message heading to server
        //   stream - stream headed towards the transport sink
        // Returns:
        //   IAsyncResult for this call. 
        [System.Security.SecurityCritical]  // auto-generated_required
        void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, 
                                 ITransportHeaders headers, Stream stream); 

        [System.Security.SecurityCritical]  // auto-generated_required 
        void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, Object state,
                                  ITransportHeaders headers, Stream stream);

        // Parameters: 
        //   msg - it's the "IMethodCallMessage"
        //   headers - headers to add to the outgoing message heading to server 
        [System.Security.SecurityCritical]  // auto-generated_required 
        Stream GetRequestStream(IMessage msg, ITransportHeaders headers);
 

        // the next channel sink in the chain
        IClientChannelSink NextChannelSink
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get; 
        } 
    } // IClientChannelSink
 


    [Serializable]
[System.Runtime.InteropServices.ComVisible(true)] 
    public enum ServerProcessing
    { 
        Complete, // server synchronously processed message 
        OneWay,   // message dispatched and no response should be sent
        Async     // the call was dispatched asynchronously 
                  //   (sink should store data on stack for later processing)
    } // ServerProcessing

 
    // Used for security sink and transport sinks.
[System.Runtime.InteropServices.ComVisible(true)] 
    public interface IServerChannelSink : IChannelSinkBase 
    {
        // Parameters: 
        //   sinkStack - channel sinks who called this one
        //   requestMsg - deserialized request message or null if the stream hasn't been deserialized
        //   requestHeaders - headers retrieved from the incoming message from client
        //   requestStream - stream to process and pass onto towards the deserialization sink. 
        //   responseMsg - response message
        //   responseHeaders - headers to add to return message heading to client 
        //   responseStream - stream heading back towards the transport sink 
        // Returns:
        //   Provides information about how message was processed. 
        [System.Security.SecurityCritical]  // auto-generated_required
        ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
                                        IMessage requestMsg,
                                        ITransportHeaders requestHeaders, Stream requestStream, 
                                        out IMessage responseMsg, out ITransportHeaders responseHeaders,
                                        out Stream responseStream); 
 
        // Parameters: (for async calls)
        //   sinkStack - sink stack (leading back to the server transport sink) 
        //   headers - headers to add to return message heading to client
        //   stream - stream heading back towards the transport sink
        [System.Security.SecurityCritical]  // auto-generated_required
        void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, Object state, 
                                  IMessage msg, ITransportHeaders headers, Stream stream);
 
        // Parameters: 
        //   sinkStack - sink stack (leading back to the server transport sink)
        //   state - state that had been pushed to the stack by this sink 
        //   msg - it's the "IMethodCallMessage"
        //   headers - headers to put in response message to client
        [System.Security.SecurityCritical]  // auto-generated_required
        Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, Object state, 
                                 IMessage msg, ITransportHeaders headers);
 
 
        // the next channel sink in the chain
        IServerChannelSink NextChannelSink 
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
        } 

    } // interface IServerChannelSink 
 

[System.Runtime.InteropServices.ComVisible(true)] 
    public interface IChannelSinkBase
    {
        // This returns a dictionary through which properties on the sink may be retrieved
        // or configured. If a property is not present in this sink, it should delegate the 
        // the property get or set to the next sink in the chain.
        IDictionary Properties 
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get; 
        }
    }

 

    // Client formatter sinks are both a message sink and a channel sink. 
    // They initially transform the message into a stream. 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface IClientFormatterSink : IMessageSink, IClientChannelSink 
    {
    } // interface IClientFormatterSink

 

 
    // Channels wishing to use the channel sink architecture must implement this interface 
    //   on their ChannelData object.
[System.Runtime.InteropServices.ComVisible(true)] 
    public interface IChannelDataStore
    {
        String[] ChannelUris
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get; 
        } 

        Object this[Object key] 
        {
            [System.Security.SecurityCritical]  // auto-generated_required
            get;
            [System.Security.SecurityCritical]  // auto-generated_required 
            set;
        } 
    } // interface IChannelDataStore 

 
    // Used to store channel data for our remoting channels
    [System.Security.SecurityCritical]  // auto-generated_required
    [Serializable]
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)] 
    [System.Runtime.InteropServices.ComVisible(true)]
    public class ChannelDataStore : IChannelDataStore 
    { 
        String[]           _channelURIs;  // list of channel uri's that map to this channel
 
        DictionaryEntry[]  _extraData;    // sink data

        // private constructor for shallow clone
        private ChannelDataStore(String[] channelUrls, DictionaryEntry[] extraData) 
        {
            _channelURIs = channelUrls; 
            _extraData = extraData; 
        }
 
        public ChannelDataStore(String[] channelURIs)
        {
            _channelURIs = channelURIs;
            _extraData = null; 
        }
 
        [System.Security.SecurityCritical]  // auto-generated 
        internal ChannelDataStore InternalShallowCopy()
        { 
            return new ChannelDataStore(_channelURIs, _extraData);
        }

 
        public String[] ChannelUris
        { 
            [System.Security.SecurityCritical] 
            get { return _channelURIs; }
            set { _channelURIs = value; } 
        }

        // implementation of IChannelDataStore
        public Object this[Object key] 
        {
            [System.Security.SecurityCritical] 
            get 
            {
                // look for matching key in extra data list 
                foreach (DictionaryEntry entry in _extraData)
                {
                    if (entry.Key.Equals(key))
                        return entry.Value; 
                }
 
                // entry not found 
                return null;
            } // get 

            [System.Security.SecurityCritical]
            set
            { 
                if (_extraData == null)
                { 
                    _extraData = new DictionaryEntry[1]; 
                    _extraData[0] = new DictionaryEntry(key, value);
                } 
                else
                {
                    int length =_extraData.Length;
                    DictionaryEntry[] newList = new DictionaryEntry[length + 1]; 
                    int co = 0;
                    for (; co < length; co++) 
                        newList[co] = _extraData[co]; 
                    newList[co] = new DictionaryEntry(key, value); // set last value
                    _extraData = newList; 
                }
            } // set
        } // Object this[Object key]
 
    } // class ChannelDataStore
 
 

 
[System.Runtime.InteropServices.ComVisible(true)]
    public interface ITransportHeaders
    {
        // Should add headers in order, and remove them if somebody tries to set 
        //   it to null.
        Object this[Object key] 
        { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get; 
            [System.Security.SecurityCritical]  // auto-generated_required
            set;
        }
 
        // This is required to handback an enumerator which iterates over all entries
        //   in the headers. 
        [System.Security.SecurityCritical]  // auto-generated_required 
        IEnumerator GetEnumerator();
    } // interface ITransportHeaders 


    // TransportHeaders is used to store a collection of headers that is used in the channel sinks.
    // The header list preserves order, and keeps headers in the order that they were originally 
    // added. You can use the foreach statement to iterate over the contents of the header list
    // which contains objects of type DictionaryEntry. Keys are required to be strings, and 
    // comparisons are done on a case-insensitive basis. 
    [System.Security.SecurityCritical]  // auto-generated_required
    [Serializable] 
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)]
    [System.Runtime.InteropServices.ComVisible(true)]
    public class TransportHeaders : ITransportHeaders
    { 
        private ArrayList _headerList; // array of type DictionaryEntry
 
        public TransportHeaders() 
        {
            // The default capacity is larger than we'll typically need so start off at 6. 
            _headerList = new ArrayList(6);
        } // TransportHeaders

 
        // dictionary like interface
        public Object this[Object key] 
        { 
            [System.Security.SecurityCritical]
            get 
            {
                String strKey = (String)key;

                // look for matching key in header list 
                foreach (DictionaryEntry entry in _headerList)
                { 
                    if (String.Compare((String)entry.Key, strKey, StringComparison.OrdinalIgnoreCase) == 0) 
                        return entry.Value;
                } 

                // entry not found
                return null;
            } // get 

            [System.Security.SecurityCritical] 
            set 
            {
                if (key == null) 
                    return;

                String strKey = (String)key;
 
                // remove this entry if it's already in the list
                int co = _headerList.Count - 1; 
                while (co >= 0) 
                {
                    String headerKey = (String)((DictionaryEntry)_headerList[co]).Key; 
                    if (String.Compare(headerKey, strKey, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        _headerList.RemoveAt(co);
                        break; 
                    }
                    co--; 
                } 

                // otherwise, add this entry 
                if (value != null)
                {
                    _headerList.Add(new DictionaryEntry(key, value));
                } 
            } // set
        } // Object this[Object key] 
 
        [System.Security.SecurityCritical]
        public IEnumerator GetEnumerator() 
        {
            return _headerList.GetEnumerator();
        } // GetEnumerator
 
    } // TransportHeaders
 
 

    // All sink providers must have a constructor that accepts a hashtable and 
    //   an ArrayList of these structures if they want to be used from a config file.
[System.Runtime.InteropServices.ComVisible(true)]
    public class SinkProviderData
    { 
        private String _name;
        private Hashtable _properties = new Hashtable(StringComparer.InvariantCultureIgnoreCase); 
        private ArrayList _children = new ArrayList(); 

        public SinkProviderData(String name) 
        {
            _name = name;
        }
 
        public String Name { get { return _name; } }
        public IDictionary Properties { get { return _properties; } } 
        public IList Children { get { return _children; } } 
    } // class SinkProviderData
 



 
    // Base implementation for channel sinks that want to supply properties.
    // The derived class only needs to implement the Keys property and this[]. 
    [System.Security.SecurityCritical]  // auto-generated_required 
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)]
    [System.Runtime.InteropServices.ComVisible(true)] 
    public abstract class BaseChannelSinkWithProperties : BaseChannelObjectWithProperties
    {
        protected BaseChannelSinkWithProperties() : base()
        { 
        }
    } // class BaseChannelSinkWithProperties 
 

    // This provides a base implementation of a channel that wants 
    // to provide a dictionary interface. It handles the complexity
    // of asking a channel sink chain for their properties.
    // Once the channel constructs its sink chain (usually only applicable
    // for server channels) it should set the SinksWithProperties property. 
    // The properties only get chained for channel sinks when the users asks
    // for the "Properties" dictionary. If you just go through the dictionary interface 
    // you'll only get the channel specific properties. 
    // The derived class only needs to implement the Keys property and this[].
    [System.Security.SecurityCritical]  // auto-generated_required 
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)]
    [System.Runtime.InteropServices.ComVisible(true)]
    public abstract class BaseChannelWithProperties : BaseChannelObjectWithProperties
    { 
        protected IChannelSinkBase SinksWithProperties = null;
 
        protected BaseChannelWithProperties() : base() 
        {
        } 

        // This is overridden so that server channels can expose the properties
        //   of their channel sinks through a flat dictionary interface.
        public override IDictionary Properties 
        {
            [System.Security.SecurityCritical]  // auto-generated_required 
            get 
            {
                // collect dictionaries for all channel sinks and return 
                //   aggregate dictionary
                ArrayList dictionaries = new ArrayList();

                // add the channel itself 
                dictionaries.Add(this);
 
                if (SinksWithProperties != null) 
                {
                    IServerChannelSink srvSink = SinksWithProperties as IServerChannelSink; 
                    if (srvSink != null)
                    {
                        while (srvSink != null)
                        { 
                            IDictionary dict = srvSink.Properties;
                            if (dict != null) 
                                dictionaries.Add(dict); 

                            srvSink = srvSink.NextChannelSink; 
                        }
                    }
                    else
                    { 
                        // we know it's a client channel sink
                        IClientChannelSink chnlSink = (IClientChannelSink)SinksWithProperties; 
 
                        while (chnlSink != null)
                        { 
                            IDictionary dict = chnlSink.Properties;
                            if (dict != null)
                                dictionaries.Add(dict);
 
                            chnlSink = chnlSink.NextChannelSink;
                        } 
                    } 
                }
 
                // return a dictionary that spans all dictionaries provided
                return new AggregateDictionary(dictionaries);
            }
        } 

    } // class BaseChannelWithProperties 
 

 



 
    // Base implementation for channel sinks that want to supply properties.
    // The derived class only needs to implement the Keys property and this[]. 
    [System.Security.SecurityCritical]  // auto-generated_required 
    [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)]
    [System.Runtime.InteropServices.ComVisible(true)] 
    public abstract class BaseChannelObjectWithProperties : IDictionary
    {
        protected BaseChannelObjectWithProperties()
        { 
        }
 
        public virtual IDictionary Properties { 
            [System.Security.SecurityCritical]  // auto-generated_required
            get { return this; } 
        }

        //
        // IDictionary implementation 
        //
 
        public virtual Object this[Object key] 
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get { return null; }
            [System.Security.SecuritySafeCritical] // overrides public transparent member
            set { throw new NotImplementedException(); }
        } // Object this[Object key] 

        public virtual ICollection Keys 
        { 
            [System.Security.SecuritySafeCritical] // overrides public transparent member
            get { return null; } 
        }

        public virtual ICollection Values
        { 
            [System.Security.SecuritySafeCritical] // overrides public transparent member
            get 
            { 
                ICollection keys = Keys;
                if (keys == null) 
                    return null;

                ArrayList values = new ArrayList();
                foreach (Object key in keys) 
                {
                    values.Add(this[key]); 
                } 

                return values; 
            }
        }

        [System.Security.SecuritySafeCritical] // overrides public transparent member 
        public virtual bool Contains(Object key)
        { 
            if (key == null) 
                return false;
 
            ICollection keySet = Keys;
            if (keySet == null)
                return false;
 
            String keyStr = key as String;
 
            foreach (Object someKey in keySet) 
            {
                if (keyStr != null) 
                {
                    String someKeyStr = someKey as String;
                    if (someKeyStr != null)
                    { 
                        // compare the key strings case-insensitively
                        if (String.Compare(keyStr, someKeyStr, StringComparison.OrdinalIgnoreCase) == 0) 
                            return true; 

                        continue; 
                    }
                }

                if (key.Equals(someKey)) 
                    return true;
            } 
 
            return false;
        } // Contains 

        public virtual bool IsReadOnly
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get { return false; }
        } 
        public virtual bool IsFixedSize 
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get { return true; }
        }

        // The following three methods should never be implemented because 
        // they don't apply to the way IDictionary is being used in this case
        // (plus, IsFixedSize returns true.) 
        [System.Security.SecuritySafeCritical] // overrides public transparent member 
        public virtual void Add(Object key, Object value) { throw new NotSupportedException(); }
        [System.Security.SecuritySafeCritical] // overrides public transparent member 
        public virtual void Clear() { throw new NotSupportedException(); }
        [System.Security.SecuritySafeCritical] // overrides public transparent member
        public virtual void Remove(Object key) { throw new NotSupportedException(); }
 
        [System.Security.SecuritySafeCritical] // overrides public transparent member
        public virtual IDictionaryEnumerator GetEnumerator() 
        { 
            return new DictionaryEnumeratorByKeys(this);
        } // GetEnumerator 


        //
        // end of IDictionary implementation 
        //
 
        // 
        // ICollection implementation
        // 

         //ICollection

        [System.Security.SecuritySafeCritical] // overrides public transparent member 
        public virtual void CopyTo(Array array, int index) { throw new NotSupportedException(); }
 
        public virtual int Count 
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get
            {
                ICollection keySet = Keys;
                if (keySet == null) 
                    return 0;
 
                return keySet.Count; 
            }
        } // Count 

        public virtual Object SyncRoot
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get { return this; }
        } 
        public virtual bool IsSynchronized 
        {
            [System.Security.SecuritySafeCritical] // overrides public transparent member 
            get { return false; }
        }

        // 
        // end of ICollection implementation
        // 
 
        //IEnumerable
        /// <internalonly/> 
        [System.Security.SecuritySafeCritical] // overrides public transparent member
        IEnumerator IEnumerable.GetEnumerator()
        {
            return new DictionaryEnumeratorByKeys(this); 
        }
 
    } // class BaseChannelObjectWithProperties 

 

    // an enumerator based off of a key set
    internal class DictionaryEnumeratorByKeys : IDictionaryEnumerator
    { 
        IDictionary _properties;
        IEnumerator _keyEnum; 
 
        public DictionaryEnumeratorByKeys(IDictionary properties)
        { 
            _properties = properties;
            _keyEnum = properties.Keys.GetEnumerator();
        } // PropertyEnumeratorByKeys
 
        public bool MoveNext() { return _keyEnum.MoveNext(); }
        public void Reset() { _keyEnum.Reset(); } 
        public Object Current { get { return Entry; } } 

        public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } } 

        public Object Key { get { return _keyEnum.Current; } }
        public Object Value { get { return _properties[Key]; } }
 
    } // DictionaryEnumeratorByKeys
 
 
    // combines multiple dictionaries into one
    //   (used for channel sink properties 
    internal class AggregateDictionary : IDictionary
    {
        private ICollection _dictionaries;
 
        public AggregateDictionary(ICollection dictionaries)
        { 
            _dictionaries = dictionaries; 
        } // AggregateDictionary
 
        //
        // IDictionary implementation
        //
 
        public virtual Object this[Object key]
        { 
            get 
            {
                foreach (IDictionary dict in _dictionaries) 
                {
                    if (dict.Contains(key))
                        return dict[key];
                } 

                return null; 
            } 

            set 
            {
                foreach (IDictionary dict in _dictionaries)
                {
                    if (dict.Contains(key)) 
                        dict[key] = value;
                } 
            } 
        } // Object this[Object key]
 
        public virtual ICollection Keys
        {
            get
            { 
                ArrayList keys = new ArrayList();
                // add keys from every dictionary 
                foreach (IDictionary dict in _dictionaries) 
                {
                    ICollection dictKeys = dict.Keys; 
                    if (dictKeys != null)
                    {
                        foreach (Object key in dictKeys)
                        { 
                            keys.Add(key);
                        } 
                    } 
                }
 
                return keys;
            }
        } // Keys
 
        public virtual ICollection Values
        { 
            get 
            {
                ArrayList values = new ArrayList(); 
                // add values from every dictionary
                foreach (IDictionary dict in _dictionaries)
                {
                    ICollection dictValues = dict.Values; 
                    if (dictValues != null)
                    { 
                        foreach (Object value in dictValues) 
                        {
                            values.Add(value); 
                        }
                    }
                }
 
                return values;
            } 
        } // Values 

        public virtual bool Contains(Object key) 
        {
            foreach (IDictionary dict in _dictionaries)
            {
                if (dict.Contains(key)) 
                    return true;
            } 
 
            return false;
        } // Contains 

        public virtual bool IsReadOnly { get { return false; } }
        public virtual bool IsFixedSize { get { return true; } }
 
        // The following three methods should never be implemented because
        // they don't apply to the way IDictionary is being used in this case 
        // (plus, IsFixedSize returns true.) 
        public virtual void Add(Object key, Object value) { throw new NotSupportedException(); }
        public virtual void Clear() { throw new NotSupportedException(); } 
        public virtual void Remove(Object key) { throw new NotSupportedException(); }

        public virtual IDictionaryEnumerator GetEnumerator()
        { 
            return new DictionaryEnumeratorByKeys(this);
        } // GetEnumerator 
 

        // 
        // end of IDictionary implementation
        //

        // 
        // ICollection implementation
        // 
 
        //ICollection
 
        public virtual void CopyTo(Array array, int index) { throw new NotSupportedException(); }

        public virtual int Count
        { 
            get
            { 
                int count = 0; 

                foreach (IDictionary dict in _dictionaries) 
                {
                    count += dict.Count;
                }
 
                return count;
            } 
        } // Count 

        public virtual Object SyncRoot { get { return this; } } 
        public virtual bool IsSynchronized { get { return false; } }

        //
        // end of ICollection implementation 
        //
 
        //IEnumerable 
        IEnumerator IEnumerable.GetEnumerator()
        { 
            return new DictionaryEnumeratorByKeys(this);
        }

    } // class AggregateDictionary 

 
 
} // namespace System.Runtime.Remoting

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
